﻿using TbShop.Web.WX;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Web;

namespace TbShop.Web.Helpers
{
    public class WeChatHelper
    {
        private static WXAccessToken AccessTokens = new WXAccessToken();
        private static string AppId = "wxf3f6c1f5465f171b";
        private static string AppSecret = "c7105a25914a8f83b0ead8fe5b564d3c";
        private static string SubMchId = "1496489242";
        private static string CallbackHost = "";
        private static string WeChatKey = "";
        public static string IP
        {
            get
            {
                string AddressIP = string.Empty;
                foreach (IPAddress _IPAddress in Dns.GetHostEntry(Dns.GetHostName()).AddressList)
                {
                    if (_IPAddress.AddressFamily.ToString() == "InterNetwork")
                    {
                        AddressIP = _IPAddress.ToString();
                    }
                }
                return AddressIP;
            }
        }
        /// <summary>
        /// 获取基础接口AccessToken
        /// </summary>
        /// <returns></returns>
        public static WXAccessToken GetDefaultAccessToken()
        {
            if (AccessTokens == null || AccessTokens.access_token == null || (DateTime.Now - AccessTokens.create_time).TotalSeconds > 7100)
            {
                var resultJson = HttpHelper.HttpGet("https://api.weixin.qq.com/cgi-bin/token", "appid=" + AppId
                    + "&secret=" + AppSecret
                    + "&grant_type=client_credential");
                var newToken = JsonConvert.DeserializeObject<WXAccessToken>(resultJson);
                newToken.create_time = DateTime.Now;
                if (AccessTokens == null)
                {
                    AccessTokens = newToken;
                }
            }
            return AccessTokens;
        }


        /// <summary>
        /// 获取微信用户
        /// </summary>
        /// <param name="openid"></param>
        /// <returns></returns>
        public static WXUser GetWXUser(string openid)
        {
            var token = GetDefaultAccessToken().access_token;
            var resultJSON = HttpHelper.HttpGet("https://api.weixin.qq.com/cgi-bin/user/info", "access_token=" + token + "&openid=" + openid + "&lang=zh_CN");
            return JsonConvert.DeserializeObject<WXUser>(resultJSON);
        }


        #region  微信支付

        /**
         * 调用统一下单，获得下单结果
         * @return 统一下单结果
         * @失败时抛异常WxPayException
         */
        private static WxData GetUnifiedOrderResult(int price, string openid, string product_id, string body, ref string description)
        {
            //统一下单
            WxData data = new WxData();
            data.SetValue("body", body);
            data.SetValue("out_trade_no", HeinQi.Framework.Common.UtilHelper.GetRandomNumber(8));
            data.SetValue("total_fee", price);
            data.SetValue("time_start", DateTime.Now.ToString("yyyyMMddHHmmss"));
            data.SetValue("time_expire", DateTime.Now.AddMinutes(10).ToString("yyyyMMddHHmmss"));
            data.SetValue("trade_type", "JSAPI");
            data.SetValue("openid", openid);
            data.SetValue("attach", product_id);

            data.SetValue("mch_id", SubMchId);
            data.SetValue("appid", AppId);
            data.SetValue("spbill_create_ip", IP);
            data.SetValue("nonce_str", UnityHelper.GenerateNonceStr());
            WxData result = WeChatHelper.UnifiedOrder(data, "/WeChatHandle/ReceivePayResult");
            if (result.IsSet("err_code_des") && !string.IsNullOrEmpty(result.GetValue("err_code_des").ToString()))
            {
                description = result.GetValue("err_code_des").ToString();
                return null;
            }
            else
            {
                if (!result.IsSet("appid") || !result.IsSet("prepay_id") || result.GetValue("prepay_id").ToString() == "")
                {
                    if (result.IsSet("return_msg"))
                        throw new WxPayException(result.GetValue("return_msg").ToString());
                    else
                        throw new WxPayException("UnifiedOrder response error!");
                }
                return result;
            }
        }

        public static string GetJsApiParameters(int price, string openid, string product_id, string sub_mch_id, string body, ref string description)
        {
            var unifiedOrderResult = GetUnifiedOrderResult(price, openid, product_id, body, ref description);
            WxData jsApiParam = new WxData();
            jsApiParam.SetValue("appId", AppId);
            jsApiParam.SetValue("timeStamp", UnityHelper.ConvertDateTimeInt(DateTime.Now).ToString());
            jsApiParam.SetValue("nonceStr", UnityHelper.GenerateNonceStr());
            jsApiParam.SetValue("package", "prepay_id=" + unifiedOrderResult.GetValue("prepay_id"));
            jsApiParam.SetValue("signType", "MD5");
            jsApiParam.SetValue("paySign", jsApiParam.MakeSign());
            string parameters = jsApiParam.ToJson();
            return parameters;
        }

        /**
        * 
        * 统一下单
        * @param WxPaydata inputObj 提交给统一下单API的参数
        * @param int timeOut 超时时间
        * @throws WxPayException 
        * @return 成功时返回，其他抛异常
        */
        public static WxData UnifiedOrder(WxData inputObj, string callbackUrl, int timeOut = 30)
        {
            callbackUrl = CallbackHost + callbackUrl;
            string url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
            //检测必填参数
            if (!inputObj.IsSet("out_trade_no"))
            {
                throw new WxPayException("缺少统一支付接口必填参数out_trade_no！");
            }
            else if (!inputObj.IsSet("body"))
            {
                throw new WxPayException("缺少统一支付接口必填参数body！");
            }
            else if (!inputObj.IsSet("total_fee"))
            {
                throw new WxPayException("缺少统一支付接口必填参数total_fee！");
            }
            else if (!inputObj.IsSet("trade_type"))
            {
                throw new WxPayException("缺少统一支付接口必填参数trade_type！");
            }

            //关联参数
            if (inputObj.GetValue("trade_type").ToString() == "JSAPI" && !inputObj.IsSet("openid"))
            {
                throw new WxPayException("统一支付接口中，缺少必填参数openid！trade_type为JSAPI时，openid为必填参数！");
            }
            if (inputObj.GetValue("trade_type").ToString() == "NATIVE" && !inputObj.IsSet("product_id"))
            {
                throw new WxPayException("统一支付接口中，缺少必填参数product_id！trade_type为JSAPI时，product_id为必填参数！");
            }

            //异步通知url未设置，则使用配置文件中的url
            if (!inputObj.IsSet("notify_url"))
            {
                inputObj.SetValue("notify_url", callbackUrl);//异步通知url
            }
            inputObj.SetValue("sign", WeChatKey);//签名

            string xml = inputObj.ToXml();

            var start = DateTime.Now;

            string response = HttpHelper.HttpXML(xml, url, false, timeOut);
            var end = DateTime.Now;
            int timeCost = (int)((end - start).TotalMilliseconds);

            WxData result = new WxData();
            result.FromXml(response);
            return result;
        }

        #endregion

        /// <summary>
        /// 获取注册JSAPI所需参数
        /// </summary>
        /// <returns></returns>
        public static string GetJsApiInfo()
        {
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            string timestamp = UnityHelper.ConvertDateTimeInt(DateTime.Now).ToString();
            string nonceStr = UnityHelper.GetRandomNumber(8);//生成签名的随机串
            string url = System.Web.HttpContext.Current.Request.Url.AbsoluteUri.ToString();//当前的地址
            string jsapi_ticket = "";
            //ticket 缓存7200秒
            if (System.Web.HttpContext.Current.Session["jsapi_ticket"] == null)
            {
                jsapi_ticket = HttpHelper.HttpGet("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + GetDefaultAccessToken().access_token + "&type=jsapi", "");
                System.Web.HttpContext.Current.Session["jsapi_ticket"] = jsapi_ticket;
                System.Web.HttpContext.Current.Session.Timeout = 7200;
            }
            else
            {
                jsapi_ticket = System.Web.HttpContext.Current.Session["jsapi_ticket"].ToString();
            }

            Dictionary<string, object> respDic = JsonConvert.DeserializeObject<Dictionary<string, object>>(jsapi_ticket);
            jsapi_ticket = respDic["ticket"].ToString();//获取ticket
            string[] ArrayList = { "jsapi_ticket=" + jsapi_ticket, "timestamp=" + timestamp, "noncestr=" + nonceStr, "url=" + url };
            var arr = ArrayList.OrderBy(z => z).ToArray();
            var arrString = string.Join("&", arr);
            var sha1 = System.Security.Cryptography.SHA1.Create();
            var sha1Arr = sha1.ComputeHash(System.Text.Encoding.UTF8.GetBytes(arrString));
            System.Text.StringBuilder enText = new System.Text.StringBuilder();
            foreach (var b in sha1Arr)
            {
                enText.AppendFormat("{0:x2}", b);
            }
            string signature = enText.ToString();
            return "{\"appId\":\"" + AppId + "\", \"timestamp\":" + timestamp + ",\"nonceStr\":\"" + nonceStr + "\",\"signature\":\"" + signature + "\"}";
        }
    }
}